const Service = require('egg').Service;
const Client = require('ssh2').Client;

Client.prototype.asyncExec = function(command) {
  return new Promise(resolve => {
    this.exec(command, (err, stream) => {
      stream.on('close', (code, signal) => {
        console.log(
            'Stream :: close :: code: ' + code + ', signal: ' + signal);
        resolve();
      }).on('data', data => {
        console.log('STDOUT: ' + data);
      }).stderr.on('data', data => {
        console.log('STDERR：' + data);
      });
    });
  });
};

/** @namespace ctx.service.vps */
class Class extends Service {

  /** 初始化 */
  async init(vps) {
    vps.update({status: 0});
    const res = await createClient(vps);
    if (!res.success)
      return res.error;
    const client = res.client;

    //升级系统
    await client.asyncExec('yum update -y');

    //安装 nvm
    await client.asyncExec(
        'curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash');
    await client.asyncExec(
        `export NVM_DIR="$HOME/.nvm"
    [ -s "$NVM_DIR/nvm.sh" ] && \\. "$NVM_DIR/nvm.sh"`);
    await client.asyncExec('command -v nvm');

    // 利用mvn安装最新版node
    await client.asyncExec(
        'NVM_NODEJS_ORG_MIRROR=http://npm.taobao.org/mirrors/node nvm install node');

    // npm库地址改为淘宝源
    await client.asyncExec(
        'npm config set registry https://registry.npm.taobao.org');

    //安装解压工具
    await client.asyncExec('yum install unzip -y');

    //输出node版本
    await client.asyncExec('node -v');

    //更新状态 初始化成功
    vps.update({status: 1});
  }

  /** 下载爬虫代码 */
  async downloadCode(vps) {
    vps.update({status: 2, last_update_code_at: new Date()});

    const res = await createClient(vps);
    if (!res.success)
      return res.error;
    const client = res.client;

    // 创建代码文件夹
    await client.asyncExec('mkdir /home/spider');

    // 下载代码
    await client.asyncExec(
        'cd /home/spider && curl --silent -o code.zip ' +
        this.app.config.spiderClient.codeUrl + '?_=' +
        Date.now());
    await client.asyncExec(
        'cd /home/spider && unzip -o code.zip && rm -f code.zip');

    // 安装运行环境
    await client.asyncExec('cd /home/spider && npm install');
    client.end();

    vps.update({status: 3});
  }

  /** 启动爬虫进程 */
  async execute(vps) {
    const res = await createClient(vps);
    if (!res.success)
      return res.error;
    const client = res.client;
    const cmd = 'cd /home/spider && npm start --token=' + vps.token
        + ' --url=' + this.app.config.spiderClient.socketUrl;
    console.log({cmd});
    await client.asyncExec(cmd);
    client.end();
  }

  /** 删除爬虫代码 */
  async deleteFolder(vps) {
    const res = await createClient(vps);
    if (!res.success)
      return res.error;
    const client = res.client;
    await client.asyncExec('rm -rf /home/spider');
    client.end();
  }

  /** 杀掉爬虫进程 */
  async kill(vps) {
    const res = await createClient(vps);
    if (!res.success)
      return res.error;
    const client = res.client;

    await client.asyncExec('cd /home/spider && npm run kill');
    client.end();
  }
}

module.exports = Class;

/**
 * 创建ssh客户端
 * @param vps
 * @return {Promise<{success: Boolean,client: Object,error: Error}>}
 */
function createClient(vps) {
  const client = new Client();
  //连接ssh
  return new Promise(resolve => {
    client.on('ready', () => {
          console.log(vps.ip + ' :: ready');
          resolve({success: true, client});
        },
    ).on('error', (error) => {
          resolve({success: false, error});
        },
    ).connect({
          host: vps.ip, port: 22, username: vps.user, password: vps.password,
        },
    );
  });
}